package com.zhanglu.gateway.filter;

import java.util.Arrays;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import com.zhanglu.gateway.security.AuthenticationUser;
import com.zhanglu.gateway.security.JwtUtil;
import com.zhanglu.gateway.token.TokenService;
import com.zhanglu.gateway.tools.JsonTools;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

import lombok.extern.slf4j.Slf4j;

/**
 * @author zhanglu
 * @description
 * @date 2017/10/23 22:21
 */
@Component
@Slf4j
public class TokenFilter extends ZuulFilter {
    @Autowired
    private TokenService tokenService;
    /**
     * 过滤器的类型
     *
     * @return pre：路由之前
     *         routing：路由之时
     *         post： 路由之后
     *         error：发送错误调用
     */
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() { // 过滤的顺序
        return 0;
    }

    @Override
    public boolean shouldFilter() { // 这里可以写逻辑判断，是否要过滤，true为过滤。false为不过滤
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        return !isPass(request.getRequestURL().toString());
    }

    @Override
    public Object run() {// 过滤器的具体逻辑
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        Cookie[] cookieArr = request.getCookies();
        if (null == cookieArr || cookieArr.length <= 0) {
            log.debug("Cookie was not found，please login!");
            writeResponse(ctx);
            return null;
        }

        String token = Arrays.stream(cookieArr).filter(cookie -> JwtUtil.COOKIE_AUTH.equalsIgnoreCase(cookie.getName()))
                .map(Cookie::getValue).findFirst().orElse(null);
        log.debug("doFilter get token from cookie is {}", token);
        if (StringUtils.isBlank(token)) {
            log.debug("token was not found，please login!");
            writeResponse(ctx);
            return null;
        }
        AuthenticationUser authenticationUser = JwtUtil.parserToken(token);
        log.debug("the user info is {}", JsonTools.showJSONStringFormat(authenticationUser));
        long expire = authenticationUser.getExpireDate().getTime();
        long now = System.currentTimeMillis();
        if (now > expire) {// 超时
            log.debug("local token time out");
            String newToken = tokenService.refreshToken(token);
            if (StringUtils.isBlank(newToken)) {
                log.debug("DB token time out");
                writeResponse(ctx);
                return null;
            }
        }
        return null;
    }

    private boolean isPass(String path) {
        return path.contains("/website/test/") || path.contains("/chatroom/auth/") || path.contains("/chatroom/test/");
    }

    private void writeResponse(RequestContext ctx) {
        log.warn("access token is empty");
        ctx.setSendZuulResponse(false);
        ctx.setResponseStatusCode(401);
    }
}
